home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / pctjja86.arc / SCROLL.ASM < prev    next >
Assembly Source File  |  1984-02-13  |  9KB  |  240 lines

  1. COMMENT * SCROLLING ROUTINE
  2.  
  3.         Scrolls the entire screen any number of lines or columns
  4.         in any direction.
  5.         Its single argument gives the direction and number of lines/cols.
  6.  
  7.         CALL SCROLL(ARG)
  8.  
  9.         If ARG is +, scrolling is up or left.
  10.         If ARG is -, scrolling is down or right.
  11.  
  12.         The magnitude of the argument gives the number of lines
  13.         and the rest of the direction information.
  14.  
  15.         If |ARG| is between 1 and 25, direction is up or down.
  16.         If |ARG| is between 257 and 336, direction is left or right, and
  17.         the number of columns is |ARG|-256.
  18.  
  19.         If rows or columns is greater than screen size or is zero,
  20.         then the screen is entirely blanked.
  21.     *
  22. ;
  23. ; Little data segment here for some temporary storage
  24. ;
  25. DGROUP    GROUP    DATA
  26. ;
  27. DATA    SEGMENT    PUBLIC 'DATA'
  28. MODE_FLAG    DB    0    ; Save mode flag returned from BIOS call
  29. CRT_COLS    DW    0    ; Save number of columns in display too.
  30. DATA    ENDS
  31. ;
  32. CODE    SEGMENT    PUBLIC 'CODE'
  33.     PUBLIC    SCROLL
  34. SCROLL    PROC    FAR
  35.     ASSUME    CS:CODE,DS:DGROUP
  36. ;
  37. ; Begin by picking up the argument from the calling routine and calling
  38. ; the BIOS for the current mode and screen size.
  39. ;
  40.     PUSH    BP        ; Save BP register
  41.     MOV    BP,SP        ; Point to stack to pick up the argument
  42.     MOV    BX,6[BP]    ; Get address of the argument
  43.     PUSH    DS        ; Save the data segment register
  44.     PUSH    ES        ; ES too in case using this with interpreter
  45.     PUSH    [BX]        ; Save the argument for later
  46.     MOV    AH,15        ; Code for "return current video state"
  47.     INT    10H        ; Call BIOS
  48.                 ; Returns: MODE in AL, COLS in AH, PAGE in BH
  49.     MOV    MODE_FLAG,AL    ; Save mode code for later
  50.     MOV    AL,AH        ; Get COLS to AL
  51.     CBW            ; Make it a word
  52.     MOV    CRT_COLS,AX    ; and save it
  53. ;
  54. ; Multiply the screen width by the screen length to get area into AX.
  55. ; Multiply by the page number to get upper left offset from the beginning
  56. ; of the display buffer.  Add to this the difference between the upper left
  57. ; and lower right addresses to get the offset from the beginning of the 
  58. ; buffer to the lower right corner of the current page being displayed.
  59. ;
  60.     MOV    CX,50        ; Assuming 25 rows always and 2 bytes/char
  61.     MUL    CL        ; Get size of screen
  62.     MOV    SI,AX        ; SI will have offset to lower right corner
  63.     DEC    SI
  64.     DEC    SI
  65.     MOV    CL,BH        ; Figure page offset
  66.     MUL    CX        ; from display buffer base
  67.     MOV    DI,AX        ; Now have upper left offset in DI
  68.     ADD    SI,DI        ; and lower right in SI
  69. ;
  70. ; Check argument to see if scroll or blank operation is requested.
  71. ; If blank, then do it right away.
  72. ;
  73.     POP    DX        ; Get the argument saved on the stack above
  74. BLANKSCREEN:
  75.     CLD            ; Assume forward direction for now
  76.     MOV    AX,DX        ; Keep a copy of the argument in AX
  77.     TEST    DX,DX        ; Which way to scroll?
  78.     JNZ    REALSCROLL    ; If non-zero, then it is a real scroll
  79. ;
  80. ; This is a blank screen operation, not a scroll.
  81. ; Blank entire screen by specifying no rows or cols for scroll and
  82. ; all rows and cols for blank operation.
  83. ;
  84.     PUSH    CRT_COLS    ; Blank all columns
  85.     MOV    AX,25        ; and
  86.     PUSH    AX        ; all rows
  87.     XOR    BX,BX        ; Scroll no rows
  88.     XOR    BP,BP        ; and no columns
  89.     JMP    COMMON        ; Proceed to common scrolling code
  90. ;
  91. ; A real scroll has been requested.  Check the sign of the argument to
  92. ; determine which corners the DI and SI registers should point to.
  93. ; If the registers must be reversed, then perform STD to reverse direction.
  94. ;
  95. REALSCROLL:
  96.     JG    FORWARD        ; If >0 then DI, SI, DF, and DX are ok
  97.     XCHG    DI,SI        ; else assume lower right corner destination.
  98.     STD            ; Need to set direction flag too.
  99.     NEG    DX        ; Get the absolute value of the argument.
  100. FORWARD:
  101.     MOV    BP,CRT_COLS    ; Get the number of columns into BP.
  102.     MOV    CX,DX        ; Put argument into CX for next check.
  103.     SUB    CX,256        ; Is the scroll vertical or horizontal?
  104.     JG    HORIZONTAL    ; Horizontal if > 256.
  105. ;
  106. ;    *****     VERTICAL SCROLL CODE     *****
  107. ;
  108. ; Check that # rows is ok.  Save parameters on stack for the blank operation
  109. ; after scroll.  Calculate the distance in bytes to move the data (including 
  110. ; the sign from the argument), and put result in DX.  Continue with common
  111. ; scroll code section.
  112. ;
  113.     MOV    BX,25        ; Total number of rows on the screen
  114.     SUB    BX,DX        ; less number moved = number to move.
  115.     JLE    SETBLANK    ; Asked for whole screen or more.
  116.     PUSH    BP        ; Save chars/row for blanking rows later.
  117.     PUSH    DX        ; Save number of rows for blanking too.
  118.     MOV    CX,160        ; There are 160 bytes per row
  119.     IMUL    CX        ; Get offset for MOVSW
  120.     MOV    DX,AX        ; Source-Destination offset into DX
  121.     JMP    COMMON        ; Proceed to common scrolling code
  122. ;
  123. ; Set up the registers to do a blank screen operation.  DX must be zero and 
  124. ; SI and DI must be swapped back if already swapped.
  125. ;
  126. SETBLANK:
  127.     XOR    DX,DX        ; Set argument to zero.
  128.     TEST    AX,AX        ; Was this a down/right operation?
  129.     JGE    BLANKSCREEN    ; No, go directly to blank screen.
  130.     XCHG    SI,DI        ; Yes, reset SI and DI before
  131.     JMP    BLANKSCREEN    ; proceeding to blank entire screen
  132. ;
  133. ;    *****     HORIZONTAL SCROLL CODE     *****
  134. ;
  135. ; Figure number of columns to move characters by.  If too large, then it's
  136. ; a blanking operation.  Set registers for common code and scroll operation.
  137. ;
  138. HORIZONTAL:
  139.     SUB    BP,CX        ; Total cols less num cols moved = # to move
  140.     JLE    SETBLANK    ; Too many cols means blank screen
  141.     PUSH    CX        ; Save number of columns to blank
  142.     MOV    DX,CX        ; Pick up words/row offset
  143.     TEST    AX,AX        ; Check sign of parameter
  144.     JG    PLUS        ; OK
  145.     NEG    DX        ; Get back correct sign
  146. PLUS:
  147.     SHL    DX,1        ; Change words to bytes
  148.     MOV    BX,25        ; Number of rows to visit
  149.     PUSH    BX        ; Save rows to blank
  150.  
  151. ;
  152. ;    *****     COMMON CODE     *****
  153. ;
  154. ; Complete the set up for the scroll by calculating the row offset (bytes 
  155. ; per row) and setting up DS and ES to point to the display buffer.
  156. ;
  157. COMMON:
  158.     MOV    CX,CRT_COLS    ; Calculate row offset: get # cols on screen.
  159.     SHL    CX,1        ; Convert from words to bytes.
  160.     TEST    AX,AX        ; Get the sign right
  161.     JGE    ARGPLUS        ; by forcing it
  162.     NEG    CX        ; to be the same as AX.
  163. ARGPLUS:
  164.     PUSH    CX        ; Save row offset for blank operation.
  165.     MOV    AX,0B000H    ; Get base segment address for mono display.
  166.     CMP    MODE_FLAG,7    ; Is this the monochrome adaptor?
  167.     JE    MONO        ; Yes, leave base address alone.
  168.     MOV    AX,0B800H    ; No, set up for color/graphics adaptor.
  169. MONO:
  170.     MOV    DS,AX        ; Use AX to set up DS
  171.     MOV    ES,AX        ; and ES.
  172. ;    
  173. ;     Now, DI points to correct corner of screen
  174. ;          SI points ot the opposite corner
  175. ;          The DF bit is set properly
  176. ;          BP = words per row to move
  177. ;          BX = number of rows to do
  178. ;          DX = destination-source offset
  179. ;          DS and ES are set to the correct segment
  180. ;
  181.     ASSUME    DS:NOTHING
  182. ;
  183. ; Perform the actual scroll here.  Get the saved row-to-row distance into 
  184. ; AX, save the opposite corner value, and set SI correctly for the MOVSW.
  185. ; The actual move uses a loop on BX to go from row to row and the 
  186. ; REP MOVSW instruction to do each row.  SI and DI must be saved before doing
  187. ; the MOVSW because they are changed by it.  Adding AX to the SI and DI sets
  188. ; them up for the next row.
  189. ;
  190.     POP    AX        ; Get row to row offset.
  191.     PUSH    AX        ; Save for blanking.
  192.     PUSH    SI        ; Save opposite corner for blanking.
  193.     MOV    SI,DI        ; Ready to adjust source by DX.
  194.     ADD    SI,DX        ; Adjust source.
  195. SCROLLOOP:
  196.     MOV    CX,BP        ; Words per row.
  197.     PUSH    SI
  198.     PUSH    DI
  199.     REP MOVSW        ; Move the words.
  200.     POP    DI
  201.     POP    SI
  202.     ADD    SI,AX        ; Point to the
  203.     ADD    DI,AX        ; next row.
  204.     DEC    BX        ; Count down.
  205.     JG    SCROLLOOP    ; Loop until all rows are done.
  206. ;
  207. ; Now must blank rows or columns.  The information needed has been saved on 
  208. ; the stack.  Retrieve it.  Put the blank character and attribute in AX in
  209. ; preparation for the REP STOSW instruction, and set the direction correctly.
  210. ; The blank operation is performed one row at a time with the REP STOSW
  211. ; instruction.  The rows are done with a loop on BX.
  212. ;
  213.     POP    DI        ; Get correct corner of the screen.
  214.     POP    DX        ; Get the row offset
  215.     POP    BX        ; and the row count
  216.     POP    BP        ; and the character count.
  217.     MOV    AX,720H        ; 720H is a blank with normal attributes.
  218.     CLD            ; Assume forward direction for STOSW.
  219.     TEST    DX,DX        ; Is it?
  220.     JL    BLANKLOOP        ; Yes, go ahead.
  221.     STD            ; No, change direction bit.
  222. BLANKLOOP:
  223.     MOV    CX,BP        ; Pick up the character count.
  224.     PUSH    DI        ; Save DI.
  225.     REP STOSW        ; Store the blanks in display buffer.
  226.     POP    DI        ; Get DI back.
  227.     SUB    DI,DX        ; Move to the next row.
  228.     DEC    BX        ; Decrement the row count
  229.     JG    BLANKLOOP    ; and keep going until all done.
  230. ;
  231. ; Scrolling and blanking is complete.  Restore saved registers and return.
  232. ;
  233.     POP    ES        ; Restore ES register.
  234.     POP    DS        ; Restore DS register.
  235.     POP    BP        ; Restore BP register.
  236.     RET            ; Return to caller.
  237. SCROLL    ENDP
  238. CODE    ENDS
  239.     END
  240.